//
//  BaseHander.m
//  GeneralProject
//
//  Created by zhangkai on 15/10/19.
//  Copyright © 2015年 AC. All rights reserved.
//

#import "HttpHander.h"
#import "BaseRequest.h"
#import "RequestHelper.h"
#import "UserModel.h"
#import "RequestUtils.h"

//缓存过期时间（分钟）
#define TimeLimit 10


@implementation HttpHander

+ (instancetype)shared {
    static dispatch_once_t onceToken;
    static HttpHander *handler = nil;
    dispatch_once(&onceToken, ^{
        handler = [[[self class] alloc] init];
    });
    return handler;
}

-(void)postAsyncRequestWithRequestName:(NSString *)requestName requestModel:(BaseRequestModel *)requestModel delegate:(id)delegate method:(SEL)sel;
{
    [[RequestCallBackDispatch shareRequestDispatch] addRequestCallBackWithRequestName:requestName className:self methodName:NSStringFromSelector(@selector(requestCallBack:))];
    
    [BaseRequest sendAsyncRequestWithRequestName:requestName requestMethod:@"POST" requestModel:requestModel delegate:delegate method:sel host:requestModel.host];
}

-(void)getAsyncRequestWithRequestName:(NSString *)requestName requestModel:(BaseRequestModel *)requestModel delegate:(id)delegate method:(SEL)sel{
    [[RequestCallBackDispatch shareRequestDispatch] addRequestCallBackWithRequestName:requestName className:self methodName:NSStringFromSelector(@selector(requestCallBack:))];
    
    [BaseRequest sendAsyncRequestWithRequestName:requestName requestMethod:@"GET" requestModel:requestModel delegate:delegate method:sel host:requestModel.host];
}


-(void)requestCallBack:(NSDictionary *)retDic
{
    if (retDic) {
        RequestResultModel *requstResultModel = [[RequestResultModel alloc] init];
        if ([[retDic objectForKey:@"ret"] integerValue] == ProtSuc) {//请求成功
            requstResultModel.success = YES;
            if ([retDic objectForKey:@"data"]) {
                requstResultModel.retDict = [retDic objectForKey:@"data"];
            }
        }else{//请求失败
            if ([retDic objectForKey:@"errorInfo"]) {
                requstResultModel.errorInfo = [retDic objectForKey:@"errorInfo"];
            }
        }
        if ([retDic objectForKey:@"requestModel"]) {
            requstResultModel.requestModel = [retDic objectForKey:@"requestModel"];
        }
        id delegate = [retDic objectForKey:@"delegate"];
        NSString *methodName = [retDic objectForKey:@"methodName"];
        if (delegate && methodName) {
            if ([delegate respondsToSelector:NSSelectorFromString(methodName)]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
                [delegate performSelector:NSSelectorFromString(methodName) withObject:requstResultModel];
#pragma clang diagnostic pop
            
            }
        }
    }
}



//带缓存的请求方法
-(void)sendAsyncRequestWithRequestModel:(BaseRequestModel *)requestModel{
    
    if (requestModel.isCache) {//带缓存
        
        //先取内存缓存，没有取文件缓存
        NSDictionary *cacheData = [self getDataWithMemoryName:[self getCacheNameWithUrl:requestModel.requestUrl] key:[self getCacheKeyNameWithRequestModel:requestModel]];
        if (!cacheData) {
            cacheData = [CacheDataLayer getPlistDataWithFileName:[self getCacheNameWithUrl:requestModel.requestUrl] keyName:[self getCacheKeyNameWithRequestModel:requestModel]];
            
        }
        
        if (cacheData && ![self isOverdueForCacheData:cacheData]) {//有缓存且未过期
            //将文件缓存保存至内存缓存
            [self saveData:cacheData ToMemoryName:[self getCacheNameWithUrl:requestModel.requestUrl] key:[self getCacheKeyNameWithRequestModel:requestModel]];
            RequestResultModel *resultModel = [[RequestResultModel alloc] init];
            resultModel.requestModel = requestModel;
            resultModel.retDict = [self getCacheData:cacheData];
            resultModel.success = YES;
            if (requestModel.delegate && requestModel.callBackMethod && [requestModel.delegate respondsToSelector:requestModel.callBackMethod]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
                [requestModel.delegate performSelector:requestModel.callBackMethod withObject:resultModel];
#pragma clang diagnostic pop
            }
        }else{//没有缓存或缓存过期
            [[RequestCallBackDispatch shareRequestDispatch] addRequestCallBackWithRequestName:requestModel.requestUrl className:self methodName:NSStringFromSelector(@selector(requestCacheCallBack:))];
            
            [BaseRequest sendAsyncRequestWithRequestName:requestModel.requestUrl requestMethod:[self getRequestMethodWithType:requestModel.requestType] requestModel:requestModel delegate:requestModel.delegate method:requestModel.callBackMethod host:requestModel.host];
        }
        
    }else{//不带缓存
        
        [[RequestCallBackDispatch shareRequestDispatch] addRequestCallBackWithRequestName:requestModel.requestUrl className:self methodName:NSStringFromSelector(@selector(requestCacheCallBack:))];
        
        [BaseRequest sendAsyncRequestWithRequestName:requestModel.requestUrl requestMethod:[self getRequestMethodWithType:requestModel.requestType] requestModel:requestModel delegate:requestModel.delegate method:requestModel.callBackMethod host:requestModel.host];
    }
}

-(void)requestCacheCallBack:(NSDictionary *)retDic
{
    if (retDic) {
        RequestResultModel *requstResultModel = [[RequestResultModel alloc] init];
        if ([retDic objectForKey:@"requestModel"]) {
            requstResultModel.requestModel = [retDic objectForKey:@"requestModel"];
        }
        if ([[retDic objectForKey:@"ret"] integerValue] == ProtSuc) {//请求成功
            requstResultModel.success = YES;
            if ([retDic objectForKey:@"data"]) {
                requstResultModel.retDict = [retDic objectForKey:@"data"];
                
                if (requstResultModel.requestModel.isCache) {//保存缓存
                    
                    //内存缓存
                    [self saveData:[self getTimeCacheData:requstResultModel.retDict] ToMemoryName:[self getCacheNameWithUrl:requstResultModel.requestModel.requestUrl] key:[self getCacheKeyNameWithRequestModel:requstResultModel.requestModel]];
                    //文件缓存
                    [CacheDataLayer saveDataToPlist:[self getTimeCacheData:requstResultModel.retDict] fileName:[self getCacheNameWithUrl:requstResultModel.requestModel.requestUrl] keyName:[self getCacheKeyNameWithRequestModel:requstResultModel.requestModel]];
                    
                }else{//不需要缓存但之前有存储过，需要将之前的缓存更新
                    
                    //先取内存缓存，没有取文件缓存
                    NSDictionary *cacheData = [self getDataWithMemoryName:[self getCacheNameWithUrl:requstResultModel.requestModel.requestUrl] key:[self getCacheKeyNameWithRequestModel:requstResultModel.requestModel]];
                    if (!cacheData) {
                        cacheData = [CacheDataLayer getPlistDataWithFileName:[self getCacheNameWithUrl:requstResultModel.requestModel.requestUrl] keyName:[self getCacheKeyNameWithRequestModel:requstResultModel.requestModel]];
                        
                    }
                    
                    if (cacheData) {
                        //更新文件缓存缓存
                        [CacheDataLayer saveDataToPlist:[self getTimeCacheData:requstResultModel.retDict] fileName:[self getCacheNameWithUrl:requstResultModel.requestModel.requestUrl] keyName:[self getCacheKeyNameWithRequestModel:requstResultModel.requestModel]];
                        //更新内存缓存
                        [self saveData:[self getTimeCacheData:requstResultModel.retDict] ToMemoryName:[self getCacheNameWithUrl:requstResultModel.requestModel.requestUrl] key:[self getCacheKeyNameWithRequestModel:requstResultModel.requestModel]];
                    }
                }
                
            }
        }else{//请求失败
            if ([retDic objectForKey:@"errorInfo"]) {
                requstResultModel.errorInfo = [retDic objectForKey:@"errorInfo"];
            }
            if ([retDic objectForKey:@"errorCode"]) {
                requstResultModel.errorCode = [NSString stringWithFormat:@"%@",[retDic objectForKey:@"errorCode"]];
            }
        }
        
        if (requstResultModel.requestModel.delegate && requstResultModel.requestModel.callBackMethod && [requstResultModel.requestModel.delegate respondsToSelector:requstResultModel.requestModel.callBackMethod]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
            [requstResultModel.requestModel.delegate performSelector:requstResultModel.requestModel.callBackMethod withObject:requstResultModel];
#pragma clang diagnostic pop
        }
    }
}

//获取请求方式
-(NSString *)getRequestMethodWithType:(NSInteger)type{
    
    switch (type) {
        case 0:
            return @"POST";
            break;
            
        case 1:
            return @"GET";
            break;
            
        default:
            return @"POST";
            break;
    }
}

//生成文件名
-(NSString *)getCacheNameWithUrl:(NSString *)url{
    UserModel *userModel = [UserModel mj_objectWithKeyValues:getUserData()];
    NSString *fileName = [NSString stringWithFormat:@"%@-%@",[userModel.Id stringValue],url];
    
    return fileName;
}

//生成key名
-(NSString *)getCacheKeyNameWithRequestModel:(BaseRequestModel *)requestModel{
    
    NSString *key = @"key";
    
    NSMutableDictionary *dict = [requestModel mj_keyValues];
    //delegate和callBackMethod类型不能存入字典
    //且缓存不与调用类及回调方法名以及是否缓存等方式做区分
    if ([dict objectForKey:@"delegate"]) {
        [dict removeObjectForKey:@"delegate"];
    }
    if ([dict objectForKey:@"callBackMethod"]) {
        [dict removeObjectForKey:@"callBackMethod"];
    }
    if ([dict objectForKey:@"isCache"]) {
        [dict removeObjectForKey:@"isCache"];
    }
    if ([dict objectForKey:@"requestType"]) {
        [dict removeObjectForKey:@"requestType"];
    }
    
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:nil];
    NSString *jsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    key = [NSString stringWithFormat:@"%@_%@",key,jsonStr];
    
    return key;
}

//生成带时间戳的缓存数据
-(NSDictionary *)getTimeCacheData:(NSDictionary *)dict{
    NSMutableDictionary *cacheDict = [[NSMutableDictionary alloc] init];
    [cacheDict setObject:dict forKey:@"Data"];
    NSDate *timeStamp = [NSDate date];
    [cacheDict setObject:timeStamp forKey:@"TimeStamp"];
    return cacheDict;
}

//根据缓存获取不带时间戳的数据
-(NSDictionary *)getCacheData:(NSDictionary *)dict{
    if ([dict objectForKey:@"Data"]) {
        return [dict objectForKey:@"Data"];
    }else{
        return nil;
    }
}

//缓存是否过期
-(BOOL)isOverdueForCacheData:(NSDictionary *)dict{
    if ([dict objectForKey:@"TimeStamp"]) {
        NSDate *timeStamp = [dict objectForKey:@"TimeStamp"];
        NSDate *now = [NSDate date];
        NSTimeInterval timeInterval = [now timeIntervalSinceDate:timeStamp];
        if (timeInterval <= 60*TimeLimit) {
            return NO;
        }
    }
    return YES;
}


#pragma mark-内存缓存
//根据key保存内存缓存
-(void)saveData:(NSDictionary *)data ToMemoryName:(NSString *)name key:(NSString *)key{
    if (!self.memoryCache) {
        self.memoryCache = [[NSMutableDictionary alloc] init];
    }
    NSMutableDictionary *subCache = [[NSMutableDictionary alloc] init];
    [subCache setObject:data forKey:key];
    [self.memoryCache setObject:subCache forKey:name];
}

//根据key取内存缓存
-(NSDictionary *)getDataWithMemoryName:(NSString *)name key:(NSString *)key{
    if (self.memoryCache) {
        NSDictionary *cache = [self.memoryCache objectForKey:name];
        if (cache) {
            NSDictionary *subCache = [cache objectForKey:key];
            if (subCache) {
                return subCache;
            }
        }
    }
    return nil;
}

//根据name保存内存缓存
-(void)saveData:(NSDictionary *)data ToMemoryName:(NSString *)name{
    if (!self.memoryCache) {
        self.memoryCache = [[NSMutableDictionary alloc] init];
    }
    [self.memoryCache setObject:data forKey:name];
}


//根据name取内存缓存
-(NSDictionary *)getDataWithMemoryName:(NSString *)name{
    if (self.memoryCache) {
        NSDictionary *cache = [self.memoryCache objectForKey:name];
        if (cache) {
            return cache;
        }
    }
    return nil;
}


@end
